/*
 * ConnectPanel.java
 *
 * Created on 21-mrt-2010, 20:49:41
 */
package nl.lemval.nododue.tabs;

import java.awt.Cursor;

import nl.lemval.nododue.cmd.CommandInfo;
import nl.lemval.nododue.component.NodoSettingsTableModel;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.table.TableColumn;
import nl.lemval.nododue.NodoDueManager;
import nl.lemval.nododue.NodoDueManagerView;
import nl.lemval.nododue.component.SettingsCellEditor;
import nl.lemval.nododue.component.SettingsCellRenderer;
import nl.lemval.nododue.dialog.WriteConfigBox;
import nl.lemval.nododue.util.NodoSetting;
import nl.lemval.nododue.util.NodoSettingRetriever;
import org.jdesktop.application.Action;
import org.jdesktop.application.Task;

/**
 * Represents a panel containing a table for all the settings of the Nodo.
 * The editable values are changeable via inline edit possibilities.
 *
 * @author Michael
 */
public class SettingsPanel extends NodoBasePanel {

    private NodoSettingsTableModel settingsTableModel;
    private SettingsCellRenderer cellRenderer;
    private SettingsCellEditor cellEditor;

    /**
     * Creates the new form. A custom table model is used for showing
     * the settings. Both column 2 and 4 (values of parameters) of the
     * table are using a custom cellRenderer/Editor to allow editing.
     */
    public SettingsPanel(final NodoDueManagerView view) {
        super(view);

        settingsTableModel = new NodoSettingsTableModel(getResourceMap());

        initComponents();

//        settingsTable.getTableHeader().setFont(getResourceFont("settingsTable.header.font"));

        cellRenderer = new SettingsCellRenderer(settingsTableModel);
        cellEditor = new SettingsCellEditor(settingsTableModel);

        TableColumn col;
        col = settingsTable.getColumnModel().getColumn(0);
        col.setCellRenderer(cellRenderer);
        col = settingsTable.getColumnModel().getColumn(1);
        col.setCellRenderer(cellRenderer);
        col = settingsTable.getColumnModel().getColumn(2);
        col.setCellRenderer(cellRenderer);
        col.setCellEditor(cellEditor);
        col = settingsTable.getColumnModel().getColumn(3);
        col.setCellRenderer(cellRenderer);
        col = settingsTable.getColumnModel().getColumn(4);
        col.setCellRenderer(cellRenderer);
        col.setCellEditor(cellEditor);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        title = new javax.swing.JLabel();
        settingsScroll = new javax.swing.JScrollPane();
        settingsTable = new javax.swing.JTable();
        download = new javax.swing.JButton();
        upload = new javax.swing.JButton();

        setFocusable(false);
        setName("Form"); // NOI18N

        title.setFont(title.getFont().deriveFont(title.getFont().getStyle() | java.awt.Font.BOLD, title.getFont().getSize()+1));
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getResourceMap(SettingsPanel.class);
        title.setText(resourceMap.getString("title.text")); // NOI18N
        title.setName("title"); // NOI18N

        settingsScroll.setName("settingsScroll"); // NOI18N

        settingsTable.setModel(settingsTableModel);
        settingsTable.setName("settingsTable"); // NOI18N
        settingsTable.setRowHeight(19);
        settingsScroll.setViewportView(settingsTable);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getActionMap(SettingsPanel.class, this);
        download.setAction(actionMap.get("updateSelected")); // NOI18N
        download.setText(resourceMap.getString("download.text")); // NOI18N
        download.setName("download"); // NOI18N

        upload.setAction(actionMap.get("writeConfiguration")); // NOI18N
        upload.setText(resourceMap.getString("upload.text")); // NOI18N
        upload.setName("upload"); // NOI18N

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, settingsScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 557, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, title)
                    .add(layout.createSequentialGroup()
                        .add(download)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(upload)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(title)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(settingsScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 313, Short.MAX_VALUE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(upload)
                    .add(download))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Task to download all settings and refresh the screen.
     * @return The new task instance if there is a connection.
     */
    @Action
    public Task updateSelected() {
        if (NodoDueManager.hasConnection()) {
            return new UpdateSelectedTask(org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class));
        }
        return null;
    }

    private class UpdateSelectedTask extends org.jdesktop.application.Task<Object, Void> {

        UpdateSelectedTask(org.jdesktop.application.Application app) {
            // Runs on the EDT.  Copy GUI state that
            // doInBackground() depends on from parameters
            // to UpdateSelectedTask fields, here.
            super(app);
        }

        /**
         * Downloads and parses all commands of type SETTING.
         * @return A Collection of NodoSetting objects
         */
        @Override
        protected Object doInBackground() {
            download.setEnabled(false);
            upload.setEnabled(false);
//            Collection<CommandInfo> cis = CommandLoader.getActions(CommandType.SETTING);
            return NodoSettingRetriever.getAllSettings();
        }

        /**
         * Refreshes the table with properties.
         * @param result The data returned by doInBackground
         */
        @Override
        protected void succeeded(Object result) {
            download.setEnabled(true);
            upload.setEnabled(true);
            Collection<NodoSetting> settings = (Collection<NodoSetting>) result;
            if (settings == null) {
                getListener().showStatusMessage(getResourceString("no.connection"));
                return;
            }
            updateSettings(settings);
        }
    }

    /**
     * Update the screen by refreshing the table model data and
     * marking the change.
     * @param settings The new settings
     */
    public void updateSettings(Collection<NodoSetting> settings) {
        settingsTableModel.clear();
        for (NodoSetting nodoSetting : settings) {
            settingsTableModel.addSetting(nodoSetting);
        }
        settingsTable.invalidate();
    }

    /**
     * Returns all collected settings with values.
     * @return All available settings.
     */
    public Collection<NodoSetting> getSettings() {
        return settingsTableModel.getSettings(true);
    }

    /**
     * Collects all settings to be written to the Nodo by displaying
     * a box with checkable categories of settings. The writing itself
     * is delegated to the NodoSettingRetriever class.
     */
    @Action
    public void writeConfiguration() {
        if (NodoDueManager.hasConnection()) {
            NodoDueManager app = NodoDueManager.getApplication();
            WriteConfigBox box = new WriteConfigBox(app.getMainFrame(), true);
            box.setLocationRelativeTo(this);
            app.show(box);

            if (box.isConfirmed()) {
                Collection<NodoSetting> writeAttrs = settingsTableModel.getSettings(false);

                Collection<String> specified = new ArrayList<String>();
                specified.addAll(CommandInfo.DATE_SET);
                specified.addAll(CommandInfo.OUT_SET);
                specified.addAll(CommandInfo.TIMER_SET);
                specified.addAll(CommandInfo.UNIT_SET);
                specified.addAll(CommandInfo.VAR_SET);
                specified.addAll(CommandInfo.WIRE_SET);

                ArrayList<String> names = new ArrayList<String>();
                if (box.includeUnitFunction()) {
                    names.addAll(CommandInfo.UNIT_SET);
                } else {
                    if (box.includeOtherFunctions()) {
                        for (NodoSetting setting : writeAttrs) {
                            String name = setting.getName();
                            if (!specified.contains(name)) {
                                names.add(setting.getName());
                            }
                        }
                    }
                    if (box.includeDateFunctions()) {
                        names.addAll(CommandInfo.DATE_SET);
                    }
                    if (box.includeOutputFunctions()) {
                        names.addAll(CommandInfo.OUT_SET);
                    }
                    if (box.includeSettings()) {
                        names.addAll(CommandInfo.VAR_SET);
                    }
                    if (box.includeTimers()) {
                        names.addAll(CommandInfo.TIMER_SET);
                    }
                    if (box.includeWireFunctions()) {
                        names.addAll(CommandInfo.WIRE_SET);
                    }
                }
                Collection<NodoSetting> results = new ArrayList<NodoSetting>();
                for (NodoSetting nodoSetting : writeAttrs) {
                    if (names.contains(nodoSetting.getName())) {
                        if (CommandInfo.TIMER_SET.contains(nodoSetting.getName()) && nodoSetting.getAttributeValue2().equals("0") ) {
                            // System.out.println("Skipping " + nodoSetting);
                        } else {
                            results.add(nodoSetting);
                        }
                    }
                }
                setCursor(new Cursor(Cursor.WAIT_CURSOR));
                download.setEnabled(false);
                upload.setEnabled(false);
                // TODO: Allow distribution
                NodoSettingRetriever.storeSettings(results, 0);
                download.setEnabled(true);
                upload.setEnabled(true);
                setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton download;
    private javax.swing.JScrollPane settingsScroll;
    private javax.swing.JTable settingsTable;
    private javax.swing.JLabel title;
    private javax.swing.JButton upload;
    // End of variables declaration//GEN-END:variables
}
